winsafe\gui\windows/
raw_main.rs1use std::cell::UnsafeCell;
2use std::marker::PhantomPinned;
3use std::pin::Pin;
4use std::sync::Arc;
5
6use crate::co;
7use crate::decl::*;
8use crate::gui::{privs::*, *};
9use crate::prelude::*;
10
11struct RawMainObj {
12 raw_base: RawBase,
13 opts: WindowMainOpts,
14 hchild_prev_focus: UnsafeCell<HWND>,
15 _pin: PhantomPinned,
16}
17
18#[derive(Clone)]
22pub(in crate::gui) struct RawMain(Pin<Arc<RawMainObj>>);
23
24impl RawMain {
25 #[must_use]
26 pub(in crate::gui) fn new(opts: WindowMainOpts) -> Self {
27 let new_self = Self(Arc::pin(RawMainObj {
28 raw_base: RawBase::new(),
29 opts,
30 hchild_prev_focus: UnsafeCell::new(HWND::NULL),
31 _pin: PhantomPinned,
32 }));
33 new_self.default_message_handlers();
34 new_self
35 }
36
37 fn default_message_handlers(&self) {
38 let self2 = self.clone();
39 self.0.raw_base.base().before_on().wm_activate(move |p| {
40 if !p.is_minimized {
41 let hchild_prev_focus = unsafe { &mut *self2.0.hchild_prev_focus.get() };
42 if p.event == co::WA::INACTIVE {
43 if let Some(hwnd_cur_focus) = HWND::GetFocus() {
44 if self2.0.raw_base.base().hwnd().IsChild(&hwnd_cur_focus) {
45 *hchild_prev_focus = hwnd_cur_focus; }
47 }
48 } else if *hchild_prev_focus != HWND::NULL {
49 hchild_prev_focus.SetFocus(); }
51 }
52 Ok(())
53 });
54
55 let self2 = self.clone();
56 self.0.raw_base.base().before_on().wm_set_focus(move |_| {
57 self2.0.raw_base.delegate_focus_to_first_child();
58 Ok(())
59 });
60
61 self.0.raw_base.base().on().wm_nc_destroy(move || {
62 PostQuitMessage(0);
63 Ok(())
64 });
65 }
66
67 #[must_use]
68 pub(in crate::gui) fn raw_base(&self) -> &RawBase {
69 &self.0.raw_base
70 }
71
72 pub(in crate::gui) fn run_main(
73 &self,
74 hinst: &HINSTANCE,
75 cmd_show: Option<co::SW>,
76 ) -> AnyResult<i32> {
77 let opts = &self.0.opts;
78 let atom = self.0.raw_base.register_class(
79 hinst,
80 &opts.class_name,
81 opts.class_style,
82 &opts.class_icon,
83 &opts.class_bg_brush,
84 &opts.class_cursor,
85 );
86
87 let sz_screen =
88 SIZE::with(GetSystemMetrics(co::SM::CXSCREEN), GetSystemMetrics(co::SM::CYSCREEN));
89
90 let pt_wnd = POINT::with(
91 sz_screen.cx / 2 - opts.size.0 / 2, sz_screen.cy / 2 - opts.size.1 / 2,
93 );
94
95 let mut rc_wnd = RECT {
96 left: pt_wnd.x, top: pt_wnd.y,
98 right: pt_wnd.x + opts.size.0 as i32,
99 bottom: pt_wnd.y + opts.size.1 as i32,
100 };
101 rc_wnd = AdjustWindowRectEx(rc_wnd, opts.style, opts.menu != HMENU::NULL, opts.ex_style)
102 .expect(DONTFAIL);
103
104 self.0.raw_base.create_window(
105 opts.ex_style,
106 atom,
107 Some(&opts.title),
108 opts.style,
109 POINT::with(rc_wnd.left, rc_wnd.top),
110 SIZE::with(rc_wnd.right - rc_wnd.left, rc_wnd.bottom - rc_wnd.top),
111 None,
112 if opts.menu == HMENU::NULL { IdMenu::None } else { IdMenu::Menu(&opts.menu) },
113 hinst,
114 );
115
116 let hwnd = self.0.raw_base.base().hwnd();
117 hwnd.ShowWindow(cmd_show.unwrap_or(co::SW::SHOW));
118 hwnd.UpdateWindow().expect(DONTFAIL);
119 BaseWnd::run_main_loop(opts.accel_table.as_deref(), opts.process_dlg_msgs) }
121}